package org.jeecg.wechat;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.riversoft.weixin.app.base.AppSetting;
import com.riversoft.weixin.app.user.SessionKey;
import com.riversoft.weixin.app.user.Users;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.math.RandomUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.constant.enums.MainErrorEnum;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.CommonUtils;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.config.wechat.WxAppletConfig;
import org.jeecg.modules.custom.entity.MtCustorm;
import org.jeecg.modules.custom.service.IMtCustomEquipService;
import org.jeecg.modules.custom.service.IMtCustormService;
import org.jeecg.modules.engineer.entity.MtEngineer;
import org.jeecg.modules.engineer.service.IMtEngineerService;
import org.jeecg.modules.equipment.entity.MtEquip;
import org.jeecg.modules.equipment.entity.MtEquipType;
import org.jeecg.modules.equipment.service.IMtEquipService;
import org.jeecg.modules.equipment.service.IMtEquipTypeService;
import org.jeecg.modules.mq.service.OrderProducerService;
import org.jeecg.modules.order.entity.MtRepairDispatch;
import org.jeecg.modules.order.entity.MtRepairEquip;
import org.jeecg.modules.order.entity.MtRepairOrder;
import org.jeecg.modules.order.entity.MtRepairSchedule;
import org.jeecg.modules.order.service.IMtRepairDispatchService;
import org.jeecg.modules.order.service.IMtRepairEquipService;
import org.jeecg.modules.order.service.IMtRepairOrderService;
import org.jeecg.modules.order.service.IMtRepairScheduleService;
import org.jeecg.modules.order.vo.MtRepairOrderPage;
import org.jeecg.modules.providers.entity.MtServiceProviders;
import org.jeecg.modules.providers.service.IMtServiceProvidersService;
import org.jeecg.modules.station.entity.MtServiceStation;
import org.jeecg.modules.station.service.IMtServiceStationService;
import org.jeecg.modules.wx.entity.MtUnionWx;
import org.jeecg.modules.wx.entity.WxLogin;
import org.jeecg.modules.wx.service.IMtUnionWxService;
import org.jeecg.wechat.request.*;
import org.jeecg.wechat.vo.CustomByCodeVo;
import org.jeecg.wechat.vo.EquipAndType;
import org.jeecg.wechat.vo.MtCustomEquipVo;
import org.jeecg.wechat.vo.UserInfoVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotBlank;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;


/**
 * @description: 报修微信小程序接口
 * @program:
 * @author: cheng
 * @date: 2022-09-09 16:21
 **/
@Api(tags = "报修微信小程序接口-v1")
@RestController
@RequestMapping("/maintain/wechat/v1")
@Slf4j
public class WeChatApi {

    final Lock lock = new ReentrantLock();
    @Autowired
    private WxAppletConfig wxAppletConfig;
    @Autowired
    private IMtUnionWxService mtUnionWxService;
    @Autowired
    private IMtCustormService mtCustormService;
    @Autowired
    private IMtCustomEquipService mtCustomEquipService;
    @Autowired
    private IMtEquipService mtEquipService;
    @Autowired
    private IMtEquipTypeService mtEquipTypeService;
    @Autowired
    private IMtServiceProvidersService mtServiceProvidersService;
    @Autowired
    private IMtServiceStationService mtServiceStationService;
    @Autowired
    private IMtEngineerService mtEngineerService;
    @Autowired
    private IMtRepairOrderService mtRepairOrderService;
    @Autowired
    private IMtRepairDispatchService mtRepairDispatchService;
    @Autowired
    private IMtRepairScheduleService mtRepairScheduleService;
    @Autowired
    private IMtRepairEquipService mtRepairEquipService;
    @Autowired
    private OrderProducerService orderProducerService;
    /**
     * 本地：local minio：minio 阿里：alioss
     */
    @Value(value = "${jeecg.uploadType}")
    private String uploadType;
    @Value(value = "${jeecg.path.upload}")
    private String uploadpath;

    /**
     * 报修微信小程序用户登录获取openid
     *
     * @param wxUserLoginRequest
     * @return
     */
    @ApiOperation(value = "wechat-报修微信小程序用户登录获取openid", notes = "wechat-报修微信小程序用户登录获取openid")
    @PostMapping("/wcLogin")
    public Result<?> wcLogin(@RequestBody WxUserLoginRequest wxUserLoginRequest) {
        SessionKey sessionKey = Users.with(new AppSetting(wxAppletConfig.getAppId(), wxAppletConfig.getSecret())).code2Session(wxUserLoginRequest.getCode());
        return Result.OK(sessionKey.getOpenId());
    }

    /**
     * 报修微信小程序用户绑定
     *
     * @param wxLogin
     * @return
     */
    @ApiOperation(value = "wechat-报修微信小程序用户绑定", notes = "wechat-报修微信小程序用户绑定")
    @PostMapping("/bindWeChat")
    public Result<MtUnionWx> bindWx(@RequestBody WxLogin wxLogin) {
        log.info("绑定-wxLogin:{}", wxLogin);
        String username = wxLogin.getUsername();
        String password = wxLogin.getPassword();
        String type = wxLogin.getUnionType();
        //判定该微信用户是否已经存在绑定记录
        List<MtUnionWx> mtUnionWxList = mtUnionWxService.list(new LambdaQueryWrapper<MtUnionWx>()
                .eq(MtUnionWx::getOpenId, wxLogin.getOpenId()));
        //记录不为空的情况,说明该微信用户已经绑定
        if (CollectionUtils.isNotEmpty(mtUnionWxList)) {
            return Result.error(MainErrorEnum.USER_IS_EXIST.getCode(), MainErrorEnum.USER_IS_EXIST.getMsg());
        }
        MtUnionWx mtUnionWx = new MtUnionWx();
        //如果是工程师
        if ("0".equals(type)) {
            MtEngineer mtEngineer = mtEngineerService.getOne(new LambdaQueryWrapper<MtEngineer>()
                    .eq(MtEngineer::getEngineerMobile, username)//工程师手机号码
                    .eq(MtEngineer::getIdCard, password), false);//工程师身份证号
            if (mtEngineer == null) {
                return Result.error(MainErrorEnum.ENGINEER_IS_NULL.getCode(), MainErrorEnum.ENGINEER_IS_NULL.getMsg());
            }
            mtUnionWx.setUnionName(mtEngineer.getEngineerName())
                    .setUnionType(type)
                    .setOpenId(wxLogin.getOpenId())
                    .setWeiXinName(wxLogin.getNickName())
                    .setOrgCode(mtEngineer.getSysOrgCode())
                    .setUserId(mtEngineer.getId());//保存工程师表数据ID
        }
        //服务商
//        else if ("1".equals(type)) {
//            SysUser sysUser = sysUserService.getUserByName(username);
//            //账号不存在
//            if (Objects.isNull(sysUser)) {
//                return Result.error(MainErrorEnum.USER_NOT_FOUND.getCode(), MainErrorEnum.USER_NOT_FOUND.getMsg());
//            }
//            String pwd = PasswordUtil.encrypt(username, password, sysUser.getSalt());
//            //密码错误
//            if (!sysUser.getPassword().equals(pwd)) {
//                return Result.error(MainErrorEnum.USER_NOT_PASSWORD.getCode(), MainErrorEnum.USER_NOT_PASSWORD.getMsg());
//            }
//            //用户已删除
//            if (CommonConstant.DEL_FLAG_1.equals(sysUser.getDelFlag())) {
//                return Result.error(MainErrorEnum.USER_IS_DEL.getCode(), MainErrorEnum.USER_IS_DEL.getMsg());
//            }
//            //用户已冻结
//            if (CommonConstant.USER_FREEZE.equals(sysUser.getStatus())) {
//                return Result.error(MainErrorEnum.USER_IS_FREEZE.getCode(), MainErrorEnum.USER_IS_FREEZE.getMsg());
//            }
//            MtServiceProviders mtServiceProviders = mtServiceProvidersService.getOne(new LambdaQueryWrapper<MtServiceProviders>()
//                    .eq(MtServiceProviders::getUserId, sysUser.getId()),false);
//            if (mtServiceProviders == null) {
//                return Result.error(MainErrorEnum.PROVIDER_IS_NULL.getCode(), MainErrorEnum.PROVIDER_IS_NULL.getMsg());
//            }
//            mtUnionWx.setUnionName(mtServiceProviders.getProName())
//                    .setUnionType(wxLogin.getUnionType())
//                    .setOpenId(wxLogin.getOpenId())
//                    .setWeiXinName(wxLogin.getNickName())
//                    .setOrgCode(mtServiceProviders.getSysOrgCode())
//                    .setUserId(mtServiceProviders.getUserId());//保存系统用户表数据ID
//        }
        //客户
        else if ("2".equals(type)) {
            MtCustorm mtCustorm = mtCustormService.getOne(new LambdaQueryWrapper<MtCustorm>()
                    .eq(MtCustorm::getCustormNo, username)//客户商户号
                    .eq(MtCustorm::getLinkPhone, password), false);//联系人手机号
            if (mtCustorm == null) {
                return Result.error(MainErrorEnum.CUSTOM_IS_NULL.getCode(), MainErrorEnum.CUSTOM_IS_NULL.getMsg());
            }
            mtUnionWx.setUnionName(mtCustorm.getCustormName())
                    .setUnionType(type)
                    .setOpenId(wxLogin.getOpenId())
                    .setWeiXinName(wxLogin.getNickName())
                    .setOrgCode(mtCustorm.getSysOrgCode())
                    .setUserId(mtCustorm.getId());//保存客户表数据ID
        }
        if (Objects.isNull(mtUnionWx)) {
            return Result.error("待绑定数据异常，绑定操作失败!");
        }
        mtUnionWxService.save(mtUnionWx);
        log.info("mtUnionWx:{}", mtUnionWx);
        return Result.OK("绑定成功！", mtUnionWx);
    }

    /**
     * 报修微信小程序用户解除绑定
     *
     * @param wxLogin
     * @return
     */
    @ApiOperation(value = "wechat-报修微信小程序用户解除绑定", notes = "wechat-报修微信小程序用户解除绑定")
    @PostMapping("/unBindWeChat")
    public Result<?> unBindWeChat(@RequestBody WxLogin wxLogin) {
        log.info("解除绑定-wxLogin:{}", wxLogin);
        String username = wxLogin.getUsername();
        String password = wxLogin.getPassword();
        String type = wxLogin.getUnionType();
        //判定该微信用户是否已经存在绑定记录
        MtUnionWx mtUnionWx = mtUnionWxService.getOne(new LambdaQueryWrapper<MtUnionWx>()
                .eq(MtUnionWx::getOpenId, wxLogin.getOpenId()).eq(MtUnionWx::getUnionType, type), false);
        if (Objects.isNull(mtUnionWx)) {
            return Result.error(500, "用户暂未绑定，不可进行解绑操作！");
        }
        //判断绑定的用户信息是否存在
        //如果是工程师
        if ("0".equals(type)) {
            MtEngineer mtEngineer = mtEngineerService.getOne(new LambdaQueryWrapper<MtEngineer>()
                    .eq(MtEngineer::getEngineerMobile, username)//工程师手机号码
                    .eq(MtEngineer::getIdCard, password), false);//工程师身份证号
            if (mtEngineer == null) {
                return Result.error(MainErrorEnum.ENGINEER_IS_NULL.getCode(), MainErrorEnum.ENGINEER_IS_NULL.getMsg());
            }
        } else if ("2".equals(type)) {
            MtCustorm mtCustorm = mtCustormService.getOne(new LambdaQueryWrapper<MtCustorm>()
                    .eq(MtCustorm::getCustormNo, username)//客户商户号
                    .eq(MtCustorm::getLinkPhone, password), false);//联系人手机号
            if (mtCustorm == null) {
                return Result.error(MainErrorEnum.CUSTOM_IS_NULL.getCode(), MainErrorEnum.CUSTOM_IS_NULL.getMsg());
            }
        }
        if (!mtUnionWxService.removeById(mtUnionWx)) {
            return Result.error(500, "用户解绑操作失败，请重试！");
        }
        return Result.ok("解除绑定操作成功！");
    }

    /**
     * 根据openid获取用户基本信息
     *
     * @param openId
     * @return userInfoVo
     */
    @ApiOperation(value = "wechat-根据openid获取用户基本信息", notes = "wechat-根据openid获取用户基本信息")
    @GetMapping("/getInfoByOpenId")
    public Result<UserInfoVo> getInfoByOpenId(@RequestParam("openId") @Validated @NotBlank(message = "用户openId不能为空") String openId) {
        if (StrUtil.isBlank(openId)) {
            return Result.error(MainErrorEnum.OPENID_NOT_NULL.getCode(), MainErrorEnum.OPENID_NOT_NULL.getMsg());
        }
        MtUnionWx mtUnionWx = mtUnionWxService.getOne(new LambdaQueryWrapper<MtUnionWx>().eq(MtUnionWx::getOpenId, openId), false);
        if (Objects.isNull(mtUnionWx)) {
            return Result.error(MainErrorEnum.USER_NOT_BIND.getCode(), MainErrorEnum.USER_NOT_BIND.getMsg());
        }
        String unionType = mtUnionWx.getUnionType();
        if (StrUtil.isBlank(unionType)) {
            return Result.error(MainErrorEnum.TYPE_NOT_BIND.getCode(), MainErrorEnum.TYPE_NOT_BIND.getMsg());
        }
        UserInfoVo userInfoVo = new UserInfoVo();
        //如果是工程师
        if ("0".equals(unionType)) {
            MtEngineer mtEngineer = mtEngineerService.getById(mtUnionWx.getUserId());
            if (mtEngineer == null) {
                return Result.error("用户绑定工程师信息不存在！");
            }
            if (StrUtil.isBlank(mtEngineer.getProviderId())) {
                return Result.error("工程师所属服务商标识为空！");
            }
            if (StrUtil.isBlank(mtEngineer.getStationId())) {
                return Result.error("工程师所属服务站标识为空！");
            }
            MtServiceProviders mtServiceProviders = mtServiceProvidersService.getById(mtEngineer.getProviderId());
            if (Objects.isNull(mtServiceProviders)) {
                return Result.error("工程师所属服务商信息不存在！");
            }
            MtServiceStation mtServiceStation = mtServiceStationService.getById(mtEngineer.getStationId());
            if (Objects.isNull(mtServiceStation)) {
                return Result.error("工程师所属服务站信息不存在！");
            }
            userInfoVo.setId(mtEngineer.getId())
                    .setIdCard(mtEngineer.getIdCard())
                    .setName(mtEngineer.getEngineerName())
                    .setMobile(mtEngineer.getEngineerMobile())
                    .setType(unionType)
                    .setSysOrgCode(mtEngineer.getSysOrgCode())
                    .setMtServiceProviders(mtServiceProviders)
                    .setMtServiceStation(mtServiceStation)
                    .setCoordinate(mtServiceStation.getCoordinate());
        }
        //如果是客户
        if ("2".equals(unionType)) {
            MtCustorm mtCustorm = mtCustormService.getById(mtUnionWx.getUserId());
            if (mtCustorm == null) {
                return Result.error("用户绑定客户信息不存在！");
            }
            if (StrUtil.isBlank(mtCustorm.getProviderId())) {
                return Result.error("客户归属服务商标识为空！");
            }
            if (StrUtil.isBlank(mtCustorm.getStationId())) {
                return Result.error("客户归属服务站标识为空！");
            }
            MtServiceProviders mtServiceProviders = mtServiceProvidersService.getById(mtCustorm.getProviderId());
            if (Objects.isNull(mtServiceProviders)) {
                return Result.error("客户归属服务商信息不存在！");
            }
            MtServiceStation mtServiceStation = mtServiceStationService.getById(mtCustorm.getStationId());
            if (Objects.isNull(mtServiceStation)) {
                return Result.error("客户归属服务站信息不存在！");
            }
            userInfoVo.setId(mtCustorm.getId())
                    .setIdCard(mtCustorm.getCustormNo())
                    .setName(mtCustorm.getCustormName())
                    .setMobile(mtCustorm.getLinkPhone())
                    .setType(unionType)
                    .setAddress(mtCustorm.getAddress())
                    .setLinkMan(mtCustorm.getLinkMan())
                    .setCoordinate(mtCustorm.getCrood())
                    .setSysOrgCode(mtCustorm.getSysOrgCode())
                    .setMtServiceProviders(mtServiceProviders)
                    .setMtServiceStation(mtServiceStation);
        }
        return Result.OK(userInfoVo);
    }

    /**
     * 文件上传统一方法
     *
     * @param request
     * @param response
     * @return
     */
    @ApiOperation(value = "wechat-文件上传统一方法", notes = "wechat-文件上传统一方法")
    @PostMapping(value = "/upload")
    public Result<?> upload(HttpServletRequest request, HttpServletResponse response) {
        Result<?> result = new Result<>();
        String savePath = "";
        String bizPath = request.getParameter("biz");

        //LOWCOD-2580 sys/common/upload接口存在任意文件上传漏洞
        if (oConvertUtils.isNotEmpty(bizPath)) {
            if (bizPath.contains(SymbolConstant.SPOT_SINGLE_SLASH) || bizPath.contains(SymbolConstant.SPOT_DOUBLE_BACKSLASH)) {
                throw new JeecgBootException("上传目录bizPath，格式非法！");
            }
        }

        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        // 获取上传文件对象
        MultipartFile file = multipartRequest.getFile("file");
        if (oConvertUtils.isEmpty(bizPath)) {
            if (CommonConstant.UPLOAD_TYPE_OSS.equals(uploadType)) {
                //未指定目录，则用阿里云默认目录 upload
                bizPath = "upload";
                //result.setMessage("使用阿里云文件上传时，必须添加目录！");
                //result.setSuccess(false);
                //return result;
            } else {
                bizPath = "";
            }
        }
        if (CommonConstant.UPLOAD_TYPE_LOCAL.equals(uploadType)) {
            //update-begin-author:lvdandan date:20200928 for:修改JEditor编辑器本地上传
            savePath = this.uploadLocal(file, bizPath);
            //update-begin-author:lvdandan date:20200928 for:修改JEditor编辑器本地上传
            /**  富文本编辑器及markdown本地上传时，采用返回链接方式
             //针对jeditor编辑器如何使 lcaol模式，采用 base64格式存储
             String jeditor = request.getParameter("jeditor");
             if(oConvertUtils.isNotEmpty(jeditor)){
             result.setMessage(CommonConstant.UPLOAD_TYPE_LOCAL);
             result.setSuccess(true);
             return result;
             }else{
             savePath = this.uploadLocal(file,bizPath);
             }
             */
        } else {
            //update-begin-author:taoyan date:20200814 for:文件上传改造
            savePath = CommonUtils.upload(file, bizPath, uploadType);
            //update-end-author:taoyan date:20200814 for:文件上传改造
        }
        if (oConvertUtils.isNotEmpty(savePath)) {
            result.setMessage(savePath);
            result.setSuccess(true);
        } else {
            result.setMessage("上传失败！");
            result.setSuccess(false);
        }
        return result;
    }

    /**
     * 本地文件上传
     *
     * @param mf      文件
     * @param bizPath 自定义路径
     * @return
     */
    private String uploadLocal(MultipartFile mf, String bizPath) {
        try {
            String ctxPath = uploadpath;
            String fileName = null;
            File file = new File(ctxPath + File.separator + bizPath + File.separator);
            if (!file.exists()) {
                // 创建文件根目录
                file.mkdirs();
            }
            // 获取文件名
            String orgName = mf.getOriginalFilename();
            orgName = CommonUtils.getFileName(orgName);
            if (orgName.indexOf(SymbolConstant.SPOT) != -1) {
                fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.lastIndexOf("."));
            } else {
                fileName = orgName + "_" + System.currentTimeMillis();
            }
            String savePath = file.getPath() + File.separator + fileName;
            File savefile = new File(savePath);
            FileCopyUtils.copy(mf.getBytes(), savefile);
            String dbpath = null;
            if (oConvertUtils.isNotEmpty(bizPath)) {
                dbpath = bizPath + File.separator + fileName;
            } else {
                dbpath = fileName;
            }
            if (dbpath.contains(SymbolConstant.DOUBLE_BACKSLASH)) {
                dbpath = dbpath.replace(SymbolConstant.DOUBLE_BACKSLASH, SymbolConstant.SINGLE_SLASH);
            }
            return dbpath;
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return "";
    }

    /**
     * 根据stationId获取工程师负责的客户
     *
     * @param stationId
     * @return userInfoVo
     */
    @ApiOperation(value = "wechat-根据stationId获取工程师负责的客户", notes = "wechat-根据stationId获取工程师负责的客户")
    @GetMapping("/getCustormListByStationId")
    public Result<List<CustomByCodeVo>> getCustormListByStationId(@RequestParam("stationId") @Validated @NotBlank(message = "服务站stationId不能为空") String stationId) {
        List<CustomByCodeVo> customByCodeVoList = new ArrayList<>();
        MtServiceStation mtServiceStation = mtServiceStationService.getById(stationId);
        if (Objects.isNull(mtServiceStation)) {
            return Result.error("服务站信息不存在！");
        }
        List<MtCustorm> custormList = mtCustormService.list(new LambdaQueryWrapper<MtCustorm>()
                .eq(MtCustorm::getStationId, stationId));
        if (CollUtil.isNotEmpty(custormList)) {
            //过滤出集合中的助记码并去重复
            List<String> codes = custormList.stream().sorted(Comparator.comparing(MtCustorm::getMnemonicCode)).map(MtCustorm::getMnemonicCode).distinct().collect(Collectors.toList());
            if (CollUtil.isNotEmpty(codes)) {
                for (String str : codes) {
                    CustomByCodeVo custom = new CustomByCodeVo();
                    custom.setCode(str);
                    List<CustomByCodeVo.Custom> customList = new ArrayList<>();
                    List<MtCustorm> mtCustorms = custormList.stream().filter(i -> str.equals(i.getMnemonicCode())).collect(Collectors.toList());
                    if (CollUtil.isNotEmpty(mtCustorms)) {
                        mtCustorms.forEach(i -> {
                            CustomByCodeVo.Custom custom1 = new CustomByCodeVo.Custom();
                            BeanUtils.copyProperties(i, custom1);
                            customList.add(custom1);
                        });
                    }
                    custom.setCustomList(customList);
                    customByCodeVoList.add(custom);
                }
            }
        }
        return Result.ok(customByCodeVoList);
    }

    /**
     * 根据客户customId获取客户设备信息
     *
     * @param customId
     * @return
     */
    @ApiOperation(value = "wechat-根据客户customId获取客户设备信息", notes = "wechat-根据客户customId获取客户设备信息")
    @GetMapping("/getCustomEquipListByCustomId")
    public Result<List<MtCustomEquipVo>> getCustomEquipListByCustomId(@RequestParam String customId) {
        if (StrUtil.isBlank(customId)) {
            return Result.error("客户的customId标识不能为空！");
        }
        List<MtCustomEquipVo> list = mtCustomEquipService.getListAndTypeCustom(customId);
        return Result.OK(list);
    }

    /**
     * 获取系统内所有设备类型
     *
     * @return
     */
    @ApiOperation(value = "wechat-获取系统内所有设备", notes = "wechat-获取系统内所有设备")
    @GetMapping("/getEquipAndTypeList")
    public Result<List<EquipAndType>> getEquipTypeList() {
        List<EquipAndType> equipAndTypeList = new ArrayList<>();
        List<MtEquipType> mtEquipTypeList = mtEquipTypeService.list();
        if (CollUtil.isNotEmpty(mtEquipTypeList)) {
            for (MtEquipType mtEquipType : mtEquipTypeList) {
                EquipAndType equipAndType = new EquipAndType();
                BeanUtils.copyProperties(mtEquipType, equipAndType);
                List<EquipAndType.Equip> equips = new ArrayList<>();
                mtEquipService.list(new LambdaQueryWrapper<MtEquip>()
                                .eq(MtEquip::getEquipTypeId, mtEquipType.getId()))
                        .forEach(i -> {
                            EquipAndType.Equip equip = new EquipAndType.Equip();
                            BeanUtils.copyProperties(i, equip);
                            equips.add(equip);
                        });
                equipAndType.setEquipList(equips);
                equipAndTypeList.add(equipAndType);
            }
        }
        return Result.OK(equipAndTypeList);
    }

    /**
     * 根据设备类型equipTypeId获取系统内设备列表
     *
     * @param equipTypeId
     * @return
     */
    @ApiOperation(value = "wechat-根据设备类型equipTypeId获取系统内设备列表", notes = "wechat-根据设备类型equipTypeId获取系统内设备列表")
    @GetMapping("/getEquipListByEquipTypeId")
    public Result<List<MtEquip>> getEquipListByEquipTypeId(@RequestParam String equipTypeId) {
        LambdaQueryWrapper<MtEquip> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MtEquip::getEquipTypeId, equipTypeId);
        List<MtEquip> list = mtEquipService.list(wrapper);
        return Result.OK(list);
    }

    /**
     * 客户/工程师报修接口
     * cheng
     * 2022-09-20
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "wechat-客户/工程师报修接口", notes = "wechat-客户/工程师报修接口")
    @PostMapping("/customRepair")
    public Result<?> CustomRepair(@RequestBody WxCustomRepairRequest request) throws InterruptedException {
        MtRepairOrder mtRepairOrder = new MtRepairOrder();
        MtRepairOrderPage mtRepairOrderPage = new MtRepairOrderPage();
        MtRepairSchedule mtRepairSchedule = new MtRepairSchedule();
        String scheduleRemarks = "";//进度描述
        String orderSource = request.getOrderSource();//工单来源：
        String skillType = request.getSkillType();//工单类型：
        String linkMan = request.getLinkMan();//联系人
        String linkMobile = request.getLinkMobile();//联系电话
        String remarks = request.getRemarks();//问题描述
        String problemPhoto = request.getProblemPhoto();//照片
        /**
         * 1.验证客户信息
         * 2.验证客户所属服务商
         * 3.如是工程师提报的报修信息  需要验证工程师信息
         * 4.将数据打成保存对象
         */
        //验证报修的客户信息是否存在
        String customId = request.getCustomId();//需要安装/维修客户ID
        MtCustorm mtCustorm = mtCustormService.getById(customId);
        if (Objects.isNull(mtCustorm)) {
            return Result.error(MainErrorEnum.CUSTOM_IS_NULL.getCode(), MainErrorEnum.CUSTOM_IS_NULL.getMsg());
        }
        mtRepairOrderPage.setCustomId(mtCustorm.getId());//客户
        //验证客户归属的服务商是否存在
        //1.验证服务商id说是不是空
        String providerId = mtCustorm.getProviderId();
        if (StrUtil.isBlank(providerId)) {
            return Result.error(MainErrorEnum.CUSTOM_NO_PROVIDER.getCode(), MainErrorEnum.CUSTOM_NO_PROVIDER.getMsg());
        }
        //2.验证 服务商id查出来的服务商对象是不是空
        MtServiceProviders mtServiceProviders = mtServiceProvidersService.getById(providerId);
        if (Objects.isNull(mtServiceProviders)) {
            return Result.error(MainErrorEnum.PROVIDER_IS_NULL.getCode(), MainErrorEnum.PROVIDER_IS_NULL.getMsg());
        }
        //3.都不为空的情况下，进行一下操作
        mtRepairOrderPage.setProviderId(providerId)//归属服务商
                .setStationId(mtCustorm.getStationId())
                .setSysOrgCode(mtServiceProviders.getSysOrgCode());//机构编码
        scheduleRemarks = "联系人：" + linkMan + "为客户：" + mtCustorm.getCustormName() + "创建了" + skillType + "工单";
        //如是工程师提报的报修信息  需要验证工程师信息
        String engineerId = request.getEngineerId();
        if (!StrUtil.isBlank(engineerId)) {
            MtEngineer mtEngineer = mtEngineerService.getById(engineerId);
            if (Objects.isNull(mtEngineer)) {
                return Result.error(MainErrorEnum.ENGINEER_IS_NULL.getCode(), MainErrorEnum.ENGINEER_IS_NULL.getMsg());
            }
            mtRepairOrderPage.setEngineerId(engineerId);//报修工程师
            mtRepairSchedule.setEngnieerId(engineerId);
            scheduleRemarks = "工程师 " + mtEngineer.getEngineerName() + "为客户 " + mtCustorm.getCustormName() + "创建了" + skillType + "工单";
        }
        mtRepairOrderPage.setOrderNo(createRepairNo())//填充工单编号
                .setOrderSource(orderSource)//工单来源
                .setSkillType(skillType)//工单分类
                .setLinkMan(linkMan)//联系人
                .setLinkMobile(linkMobile)//联系电话
                .setRemarks(remarks)//备注
                .setProblemPhoto(problemPhoto)//反应问题的照片
                .setProcessingStatus("0")//处理进度默认值
                .setBackStatus("0")//设置反馈状态默认值
                .setCreateTime(DateUtil.date());
        //商户设备数据/待安装设备数据组装
        List<WxCustomRepairRequest.WxCustomRepairEquip> repairEquipList = request.getRepairEquipList();
        List<MtRepairEquip> list = new ArrayList<MtRepairEquip>();
        if (CollUtil.isNotEmpty(repairEquipList)) {
            list = repairEquipList.stream().map(repairEquip -> {
                MtRepairEquip mtRepairEquip = new MtRepairEquip();
                BeanUtils.copyProperties(repairEquip, mtRepairEquip);
                mtRepairEquip.setSysOrgCode(mtServiceProviders.getSysOrgCode());
                return mtRepairEquip;
            }).collect(Collectors.toList());
            mtRepairOrderPage.setMtRepairEquipList(list);
        }
        //工单进度数据组装
        mtRepairSchedule.setSysOrgCode(mtServiceProviders.getSysOrgCode())
                .setCreateTime(DateUtil.date())
                .setScheduleStatus(0)//新建
                .setRemarks(scheduleRemarks)
                .setCreateTime(DateUtil.date())
                .setScheduleTime(DateUtil.date());
        List<MtRepairSchedule> scheduleList = new ArrayList<>();
        scheduleList.add(mtRepairSchedule);
        if (CollUtil.isNotEmpty(scheduleList)) {
            mtRepairOrderPage.setMtRepairScheduleList(scheduleList);
        }
        //保存数据
        BeanUtils.copyProperties(mtRepairOrderPage, mtRepairOrder);
        mtRepairOrderService.saveMain(mtRepairOrder, mtRepairOrderPage.getMtRepairDispatchList(), mtRepairOrderPage.getMtRepairEquipList(), mtRepairOrderPage.getMtRepairScheduleList(), mtRepairOrderPage.getMtRepairFeedbackList(), mtRepairOrderPage.getMtRepairDisposeList());
        log.info("已保存订单数据：mtRepairOrderPage:{}", JSONObject.toJSONString(mtRepairOrderPage));
        //将数据发送到自动派单队列
        boolean flag = orderProducerService.sendTopicOrderMessage(mtRepairOrderPage);
        if (!flag) {
            return Result.error(skillType + "信息发送自动派单队列失败,请重新提交！orderNo >>>{} " + mtRepairOrderPage.getOrderNo());
        }
        return Result.ok(skillType + "信息已提交，请关注进一步的处理结果！");
    }

    /**
     * 生成工单编号
     * cheng
     * 2022-09-21
     *
     * @return
     */
    private String createRepairNo() {
        String value = "";
        lock.lock();
        try {
            String prefix = "GD";
            SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
            int random = RandomUtils.nextInt(90) + 10;
            value = prefix + format.format(new Date()) + random;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return value;
    }

    /**
     * 工单派工
     *
     * @param request
     * @return
     * @Auth cheng
     * 2022-09-22
     */
    @ApiOperation(value = "wechat-工单派工", notes = "wechat-工单派工")
    @PostMapping("/repairDispatch")
    @Transactional(rollbackFor = Exception.class)
    public Result<?> repairDispatch(@RequestBody WxRepairDispatchRequest request) {
        MtRepairSchedule mtRepairSchedule = new MtRepairSchedule();
        String orderId = request.getOrderId();
        //验证工单是否存在
        MtRepairOrder mtRepairOrder = mtRepairOrderService.getById(orderId);
        if (Objects.isNull(mtRepairOrder)) {
            return Result.error(MainErrorEnum.ORDER_IS_NULL.getCode(), MainErrorEnum.ORDER_IS_NULL.getMsg());
        }
        List<WxRepairDispatchRequest.RepairEngineer> engineerList = request.getEngineerList();
        List<MtRepairDispatch> list = new ArrayList<>();
        if (CollUtil.isNotEmpty(engineerList)) {
            list = engineerList.stream().map(repairEngineer -> {
                MtRepairDispatch mtRepairDispatch = new MtRepairDispatch();
                BeanUtils.copyProperties(repairEngineer, mtRepairDispatch);
                mtRepairDispatch.setOrderId(orderId);
                mtRepairDispatch.setProviderId(mtRepairOrder.getProviderId());
                mtRepairDispatch.setStationId(mtRepairOrder.getStationId());
                mtRepairDispatch.setWorkStatus(0);//未接单状态
                mtRepairDispatch.setDispatchTime(DateUtil.date());
                mtRepairDispatch.setSysOrgCode(mtRepairOrder.getSysOrgCode());
                return mtRepairDispatch;
            }).collect(Collectors.toList());
        }
        if (!CollUtil.isNotEmpty(list)) {
            return Result.error("派工组装数据为空，派工操作失败！");
        }
        String scheduleRemarks = "";//工作进度描述
        for (MtRepairDispatch mtRepairDispatch : list) {
            MtEngineer mtEngineer = mtEngineerService.getById(mtRepairDispatch.getEngineerId());
            if (Objects.nonNull(mtEngineer)) {
                scheduleRemarks += mtRepairDispatch.getDispatchTime() + "  编号:" + mtRepairOrder.getOrderNo() + "的工单指派给：" + mtRepairDispatch.getWorkType() + "-" + mtEngineer.getEngineerName() + "。";
            }
        }
        mtRepairDispatchService.saveBatch(list);//保存派工信息
        //更改工单状态
        mtRepairOrder.setProcessingStatus("1");//改为已派工
        mtRepairOrderService.updateById(mtRepairOrder);
        //工单进度表信息更新
        mtRepairSchedule.setOrderId(mtRepairOrder.getId())
                .setSysOrgCode(mtRepairOrder.getSysOrgCode())
                .setCreateTime(DateUtil.date())
                .setScheduleStatus(1)//派工
                .setRemarks(scheduleRemarks)
                .setCreateTime(DateUtil.date())
                .setScheduleTime(DateUtil.date());
        mtRepairScheduleService.save(mtRepairSchedule);
        return Result.ok("派工操作成功！");
    }

    /**
     * 工程师接单
     *
     * @param request
     * @return
     * @Auth cheng
     * 2022-09-22
     */
    @ApiOperation(value = "wechat-工程师接单", notes = "wechat-工程师接单")
    @PostMapping("/repairTakeOrder")
    @Transactional(rollbackFor = Exception.class)
    public Result<?> repairTakeOrder(@RequestBody WxTakeOrderRequest request) {
        MtRepairSchedule mtRepairSchedule = new MtRepairSchedule();
        String orderId = request.getOrderId();
        if (StrUtil.isBlank(orderId)) {
            return Result.error("工单记录唯一标识为空！");
        }
        //验证工单是否存在
        MtRepairOrder mtRepairOrder = mtRepairOrderService.getById(orderId);
        if (Objects.isNull(mtRepairOrder)) {
            return Result.error(MainErrorEnum.ORDER_IS_NULL.getCode(), MainErrorEnum.ORDER_IS_NULL.getMsg());
        }
        //验证派工记录是否存在
        String dispatchId = request.getDispatchId();
        if (StrUtil.isBlank(dispatchId)) {
            return Result.error("派工记录唯一标识为空！");
        }
        MtRepairDispatch mtRepairDispatch = mtRepairDispatchService.getById(dispatchId);
        if (Objects.isNull(mtRepairDispatch)) {
            return Result.error(MainErrorEnum.DISPATCH_IS_NULL.getCode(), MainErrorEnum.DISPATCH_IS_NULL.getMsg());
        }
        //判断派工记录的状态
        if (mtRepairDispatch.getWorkStatus() == 1) {
            return Result.error("派工记录已完成接单，不可重复操作！");
        }
        //验证工程师是否存在
        String engineerId = request.getEngineerId();
        if (StrUtil.isBlank(engineerId)) {
            return Result.error("工程师身份唯一标识为空！");
        }
        MtEngineer mtEngineer = mtEngineerService.getById(engineerId);
        if (Objects.isNull(mtEngineer)) {
            return Result.error(MainErrorEnum.ENGINEER_IS_NULL.getCode(), MainErrorEnum.ENGINEER_IS_NULL.getMsg());
        }
        //验证派工信息是否是接单工程师的派工信息
        if (!mtEngineer.getId().equals(mtRepairDispatch.getEngineerId())) {
            return Result.error("该派工记录不属于接单工程师！");
        }
        //更改工单状态
        mtRepairOrder.setProcessingStatus("2");//设置为已接单状态
        mtRepairOrderService.updateById(mtRepairOrder);
        //更改派工记录状态
        mtRepairDispatch.setWorkStatus(1);//设置接单人已接单
        mtRepairDispatchService.updateById(mtRepairDispatch);
        //更改待维修/安装设备列表的归属
        List<MtRepairEquip> mtRepairEquipList = mtRepairEquipService.list(new LambdaQueryWrapper<MtRepairEquip>().eq(MtRepairEquip::getOrderId, mtRepairOrder.getId()));
        if (CollUtil.isNotEmpty(mtRepairEquipList)) {
            for (MtRepairEquip re : mtRepairEquipList) {
                MtRepairEquip mtRepairEquip = re;
                if ("负责".equals(mtRepairDispatch.getWorkType())) {
                    if (StrUtil.isBlank(mtRepairEquip.getProviderId()) || StrUtil.isBlank(mtRepairEquip.getStationId()) || StrUtil.isBlank(mtRepairEquip.getEngineerId())) {
                        mtRepairEquip.setProviderId(mtEngineer.getProviderId())
                                .setStationId(mtEngineer.getStationId())
                                .setEngineerId(mtEngineer.getId());
                        mtRepairEquipService.updateById(mtRepairEquip);
                    }
                }
            }
        }
        //保存进度记录
        String scheduleRemarks = mtEngineer.getEngineerName() + "于" + DateUtil.date() + "接单，工单：" + mtRepairOrder.getOrderNo();
        mtRepairSchedule.setOrderId(mtRepairOrder.getId());
        mtRepairSchedule.setSysOrgCode(mtRepairOrder.getSysOrgCode());
        mtRepairSchedule.setCreateTime(DateUtil.date());
        mtRepairSchedule.setScheduleStatus(2);//接单
        mtRepairSchedule.setRemarks(scheduleRemarks);
        mtRepairSchedule.setCreateTime(DateUtil.date());
        mtRepairSchedule.setScheduleTime(DateUtil.date());
        mtRepairScheduleService.save(mtRepairSchedule);
        return Result.ok("接单操作成功！");
    }

    /**
     * 处理工单
     *
     * @param request
     * @return
     * @Auth cheng
     * 2022-09-22
     */
    @ApiOperation(value = "wechat-处理工单", notes = "wechat-处理工单")
    @PostMapping("/repairDisposeOrder")
    @Transactional(rollbackFor = Exception.class)
    public Result<?> repairDisposeOrder(@RequestBody WxDisposeOrderRequest request) {


        return Result.ok();
    }


    //自动派单操作
    public Result<?> repairAutoDispatch() {
        //获取待派工工单
        List<MtRepairOrder> mtRepairOrders = mtRepairOrderService.list(new LambdaQueryWrapper<MtRepairOrder>()
                .eq(MtRepairOrder::getProcessingStatus, "0"));
        if (CollUtil.isEmpty(mtRepairOrders)) {
            return Result.ok();
        }
        //工单自动派工操作
        mtRepairOrders.forEach(i ->
        {
            MtRepairOrder mtRepairOrder = mtRepairOrderService.getById(i.getId());
            if (Objects.isNull(mtRepairOrder)) {

            }
        });
        return Result.error(500, "自动派单操作失败，请联系管理员！");
    }

    public Result<?> repairOrderDispatch(WxRepairDispatchRequest request) {
        MtRepairSchedule mtRepairSchedule = new MtRepairSchedule();
        String orderId = request.getOrderId();
        //验证工单是否存在
        MtRepairOrder mtRepairOrder = mtRepairOrderService.getById(orderId);
        if (Objects.isNull(mtRepairOrder)) {
            return Result.error(MainErrorEnum.ORDER_IS_NULL.getCode(), MainErrorEnum.ORDER_IS_NULL.getMsg());
        }
        List<WxRepairDispatchRequest.RepairEngineer> engineerList = request.getEngineerList();
        List<MtRepairDispatch> list = new ArrayList<>();
        if (CollUtil.isNotEmpty(engineerList)) {
            list = engineerList.stream().map(repairEngineer -> {
                MtRepairDispatch mtRepairDispatch = new MtRepairDispatch();
                BeanUtils.copyProperties(repairEngineer, mtRepairDispatch);
                mtRepairDispatch.setOrderId(orderId);
                mtRepairDispatch.setProviderId(mtRepairOrder.getProviderId());
                mtRepairDispatch.setStationId(mtRepairOrder.getStationId());
                mtRepairDispatch.setWorkStatus(0);//未接单状态
                mtRepairDispatch.setDispatchTime(DateUtil.date());
                mtRepairDispatch.setSysOrgCode(mtRepairOrder.getSysOrgCode());
                return mtRepairDispatch;
            }).collect(Collectors.toList());
        }
        if (!CollUtil.isNotEmpty(list)) {
            return Result.error("派工组装数据为空，派工操作失败！");
        }
        String scheduleRemarks = "";//工作进度描述
        for (MtRepairDispatch mtRepairDispatch : list) {
            MtEngineer mtEngineer = mtEngineerService.getById(mtRepairDispatch.getEngineerId());
            if (Objects.nonNull(mtEngineer)) {
                scheduleRemarks += mtRepairDispatch.getDispatchTime() + "  编号:" + mtRepairOrder.getOrderNo() + "的工单指派给：" + mtRepairDispatch.getWorkType() + "-" + mtEngineer.getEngineerName() + "。";
            }
        }
        mtRepairDispatchService.saveBatch(list);//保存派工信息
        //更改工单状态
        mtRepairOrder.setProcessingStatus("1");//改为已派工
        mtRepairOrderService.updateById(mtRepairOrder);
        //工单进度表信息更新
        mtRepairSchedule.setOrderId(mtRepairOrder.getId())
                .setSysOrgCode(mtRepairOrder.getSysOrgCode())
                .setCreateTime(DateUtil.date())
                .setScheduleStatus(1)//派工
                .setRemarks(scheduleRemarks)
                .setCreateTime(DateUtil.date())
                .setScheduleTime(DateUtil.date());
        mtRepairScheduleService.save(mtRepairSchedule);
        return Result.ok("派工操作成功！");
    }
    /****************************************************工单部分接口结束***************************************************/

}
